package com.csgc.camera.widget.stickerView;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;

import androidx.annotation.ColorInt;
import androidx.annotation.Dimension;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;

import com.csgc.camera.util.ResourceExtKt;
import com.cysd.spsyxj.R;

/**
 * Customize your sticker with text and image background.
 * You can place some text into a given region, however,
 * you can also add a plain text sticker. To support text
 * See https://adilatwork.blogspot.com/2014/08/android-textview-which-resizes-its-text.html
 * Notice: It's not efficient to add long text due to too much of
 * StaticLayout object allocation.
 * Created by liutao on 30/11/2016.
 */

public class TextSticker extends Sticker {

  /**
   * Our ellipsis string.
   */
  private static final String mEllipsis = "\u2026";

  private final Context context;
  private final Rect realBounds;
  private final Rect textRect;
  private final TextPaint textPaint;
  private Drawable drawable;
  private StaticLayout staticLayout;
  private Layout.Alignment alignment;
  private String text;

  /**
   * Upper bounds for text size.
   * This acts as a starting point for resizing.
   */
  private float maxTextSizePixels;

  /**
   * Lower bounds for text size.
   */
  private float minTextSizePixels;

  /**
   * Line spacing multiplier.
   */
  private float lineSpacingMultiplier = 1.0f;

  /**
   * Additional line spacing.
   */
  private float lineSpacingExtra = 0.0f;

  // 在 TextSticker 类中添加以下字段
  private Drawable leftIconDrawable;
  private int leftIconPadding = 10; // 图标与文本之间的间距
  private int leftIconSize = 10;

  public TextSticker(@NonNull Context context) {
    this(context, null);
  }

  public TextSticker(@NonNull Context context, @Nullable Drawable drawable) {
    this.context = context;
    this.drawable = drawable;
    if (drawable == null) {
      this.drawable = ContextCompat.getDrawable(context, R.drawable.sticker_transparent_background);
    }
    textPaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
    realBounds = new Rect(0, 0, getWidth(), getHeight());
    textRect = new Rect(0, 0, getWidth(), getHeight());
    minTextSizePixels = convertSpToPx(6);
    maxTextSizePixels = convertSpToPx(32);
    alignment = Layout.Alignment.ALIGN_CENTER;
    textPaint.setTextSize(maxTextSizePixels);

    // 添加默认值初始化
    leftIconPadding = ResourceExtKt.dpToPx(5); // 5dp 转换为像素
    leftIconSize = ResourceExtKt.dpToPx(24);   // 24dp 转换为像素
  }

  // 修改 setDrawable 方法
  @Override
  public TextSticker setDrawable(@NonNull Drawable drawable) {
    this.drawable = drawable;
    updateLayout();
    return this;
  }

  // 修改 setDrawable 带 region 参数的方法
  @NonNull
  public TextSticker setDrawable(@NonNull Drawable drawable, @Nullable Rect region) {
    this.drawable = drawable;
    updateLayout(region);
    return this;
  }

  // 在 setLeftIcon 方法中更新 textRect
  @NonNull
  public TextSticker setLeftIcon(@Nullable Drawable iconDrawable) {
    this.leftIconDrawable = iconDrawable;
    if (iconDrawable != null) {
      iconDrawable.setBounds(0, 0, leftIconSize, leftIconSize);
    }
    updateLayout();
    return this;
  }

  // 添加设置左侧图标大小的方法
  @NonNull
  public TextSticker setLeftIconSize(int sizeInPx) {
    this.leftIconSize = sizeInPx;
    if (leftIconDrawable != null) {
      leftIconDrawable.setBounds(0, 0, leftIconSize, leftIconSize);
    }
    updateLayout();
    return this;
  }

  // 添加设置图标间距的方法
  @NonNull
  public TextSticker setLeftIconPadding(int paddingInPx) {
    this.leftIconPadding = paddingInPx;
    updateLayout();
    return this;
  }

  // 统一的布局更新方法
  private void updateLayout() {
    updateLayout(null);
  }

  private void updateLayout(@Nullable Rect region) {
    int totalWidth = getWidth();
    int totalHeight = getHeight();
    realBounds.set(0, 0, totalWidth, totalHeight);

    if (region == null) {
      // 计算文字区域，考虑图标占用空间
      int textAreaLeft = 0;
      int textAreaWidth = totalWidth;

      if (leftIconDrawable != null) {
        textAreaLeft = leftIconSize + leftIconPadding;
        textAreaWidth = totalWidth - textAreaLeft;
      }

      textRect.set(textAreaLeft, 0, textAreaLeft + textAreaWidth, totalHeight);
    } else {
      textRect.set(region.left, region.top, region.right, region.bottom);
    }

    // 如果有文本，重新调整文本大小
    if (text != null && !text.isEmpty()) {
      resizeText();
    }
  }

  // 修改 draw 方法
  @Override
  public void draw(@NonNull Canvas canvas) {
    Matrix matrix = getMatrix();
    canvas.save();
    canvas.concat(matrix);

    // 绘制背景
    if (drawable != null) {
      drawable.setBounds(realBounds);
      drawable.draw(canvas);
    }

    // 绘制左侧图标
    if (leftIconDrawable != null) {
      int iconTop = getHeight() / 2 - leftIconSize / 2; // 垂直居中
      int iconLeft = 0;
      leftIconDrawable.setBounds(iconLeft, iconTop, iconLeft + leftIconSize, iconTop + leftIconSize);
      leftIconDrawable.draw(canvas);
    }

    // 绘制文字 - 只在 textRect 区域内绘制
    if (staticLayout != null) {
      canvas.save();
      // 将画布平移到文字区域开始绘制
      int translateX = textRect.left;
      int translateY = textRect.top + (textRect.height() - staticLayout.getHeight()) / 2;
      canvas.translate(translateX, translateY);

      staticLayout.draw(canvas);
      canvas.restore();
    }

    canvas.restore();
  }

  @Override
  public int getWidth() {
    return drawable != null ? drawable.getIntrinsicWidth() : 0;
  }

  @Override
  public int getHeight() {
    return drawable != null ? drawable.getIntrinsicHeight() : 0;
  }

  @Override
  public void release() {
    super.release();
    if (drawable != null) {
      drawable = null;
    }
  }

  @NonNull
  @Override
  public TextSticker setAlpha(@IntRange(from = 0, to = 255) int alpha) {
    textPaint.setAlpha(alpha);
    return this;
  }

  @NonNull
  @Override
  public Drawable getDrawable() {
    return drawable;
  }

  @NonNull
  public TextSticker setTypeface(@Nullable Typeface typeface) {
    textPaint.setTypeface(typeface);
    return this;
  }

  @NonNull
  public TextSticker setTextColor(@ColorInt int color) {
    textPaint.setColor(color);
    return this;
  }

  @NonNull
  public TextSticker setTextAlign(@NonNull Layout.Alignment alignment) {
    this.alignment = alignment;
    return this;
  }

  @NonNull
  public TextSticker setMaxTextSize(@Dimension(unit = Dimension.SP) float size) {
    textPaint.setTextSize(convertSpToPx(size));
    maxTextSizePixels = textPaint.getTextSize();
    return this;
  }

  /**
   * Sets the lower text size limit
   *
   * @param minTextSizeScaledPixels the minimum size to use for text in this view,
   * in scaled pixels.
   */
  @NonNull
  public TextSticker setMinTextSize(float minTextSizeScaledPixels) {
    minTextSizePixels = convertSpToPx(minTextSizeScaledPixels);
    return this;
  }

  @NonNull
  public TextSticker setLineSpacing(float add, float multiplier) {
    lineSpacingMultiplier = multiplier;
    lineSpacingExtra = add;
    return this;
  }

  @NonNull
  public TextSticker setText(@Nullable String text) {
    this.text = text;
    if (text != null && !text.isEmpty()) {
      resizeText();
    }
    return this;
  }

  @Nullable
  public String getText() {
    return text;
  }

  /**
   * Resize this view's text size with respect to its width and height
   * (minus padding). You should always call this method after the initialization.
   */
  @NonNull
  public TextSticker resizeText() {
    final int availableHeightPixels = textRect.height();
    final int availableWidthPixels = textRect.width();
    final CharSequence text = getText();

    // Safety check
    if (text == null
            || text.length() <= 0
            || availableHeightPixels <= 0
            || availableWidthPixels <= 0
            || maxTextSizePixels <= 0) {
      return this;
    }

    float targetTextSizePixels = maxTextSizePixels;
    int targetTextHeightPixels =
            getTextHeightPixels(text, availableWidthPixels, targetTextSizePixels);

    // Until we either fit within our TextView
    // or we have reached our minimum text size,
    // incrementally try smaller sizes
    while (targetTextHeightPixels > availableHeightPixels
            && targetTextSizePixels > minTextSizePixels) {
      targetTextSizePixels = Math.max(targetTextSizePixels - 2, minTextSizePixels);
      targetTextHeightPixels =
              getTextHeightPixels(text, availableWidthPixels, targetTextSizePixels);
    }

    // If we have reached our minimum text size and the text still doesn't fit,
    // append an ellipsis
    if (targetTextSizePixels == minTextSizePixels
            && targetTextHeightPixels > availableHeightPixels) {
      TextPaint textPaintCopy = new TextPaint(textPaint);
      textPaintCopy.setTextSize(targetTextSizePixels);

      StaticLayout staticLayout =
              new StaticLayout(text, textPaintCopy, availableWidthPixels, Layout.Alignment.ALIGN_NORMAL,
                      lineSpacingMultiplier, lineSpacingExtra, false);

      if (staticLayout.getLineCount() > 0) {
        int lastLine = staticLayout.getLineForVertical(availableHeightPixels) - 1;

        if (lastLine >= 0) {
          int startOffset = staticLayout.getLineStart(lastLine);
          int endOffset = staticLayout.getLineEnd(lastLine);
          float lineWidthPixels = staticLayout.getLineWidth(lastLine);
          float ellipseWidth = textPaintCopy.measureText(mEllipsis);

          while (availableWidthPixels < lineWidthPixels + ellipseWidth) {
            endOffset--;
            lineWidthPixels =
                    textPaintCopy.measureText(text.subSequence(startOffset, endOffset + 1).toString());
          }

          setText(text.subSequence(0, endOffset) + mEllipsis);
        }
      }
    }

    textPaint.setTextSize(targetTextSizePixels);
    staticLayout =
            new StaticLayout(this.text, textPaint, availableWidthPixels, alignment, lineSpacingMultiplier,
                    lineSpacingExtra, true);
    return this;
  }

  /**
   * @return lower text size limit, in pixels.
   */
  public float getMinTextSizePixels() {
    return minTextSizePixels;
  }

  /**
   * Sets the text size of a clone of the view's {@link TextPaint} object
   * and uses a {@link StaticLayout} instance to measure the height of the text.
   *
   * @return the height of the text when placed in a view
   * with the specified width
   * and when the text has the specified size.
   */
  protected int getTextHeightPixels(@NonNull CharSequence source, int availableWidthPixels,
                                    float textSizePixels) {
    textPaint.setTextSize(textSizePixels);
    StaticLayout staticLayout =
            new StaticLayout(source, textPaint, availableWidthPixels, Layout.Alignment.ALIGN_NORMAL,
                    lineSpacingMultiplier, lineSpacingExtra, true);
    return staticLayout.getHeight();
  }

  /**
   * @return the number of pixels which scaledPixels corresponds to on the device.
   */
  private float convertSpToPx(float scaledPixels) {
    return scaledPixels * context.getResources().getDisplayMetrics().scaledDensity;
  }
}